package com.mxx.tomcat.verification;

import com.fasterxml.jackson.databind.JavaType;
import com.mxx.common.conv.JacksonConverter;
import com.mxx.common.exception.CommentException;
import com.mxx.common.exception.JsonProcessException;
import com.mxx.common.exception.UnsupportedException;
import com.mxx.common.exception.ValidateException;
import com.mxx.tomcat.ResponseWriter;
import com.mxx.tomcat.verification.annotation.Url;
import com.mxx.tomcat.verification.annotation.Verify;
import com.mxx.tomcat.verification.annotation.WebVerification;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.lang.reflect.Type;
import java.util.List;

/**
 * @Author itzgyw
 * @Date 2020-02-28
 * @Time 21:15
 * @Description:
 */
@Slf4j
public class UrlValidateArgumentResolver extends AbstractFormUrlValidateArgumentResolver {

    private Verify.Type type = Verify.Type.URL;

    public UrlValidateArgumentResolver(List<HttpMessageConverter<?>> converters, JacksonConverter jacksonConverter, ResponseWriter responseWriter) {
        super(converters, jacksonConverter, responseWriter);

    }

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        WebVerification webVerification = methodParameter.getMethodAnnotation(WebVerification.class);
        if (methodParameter.getParameterAnnotation(Url.class) != null) {
            Verify verify = super.getVerify(webVerification, Verify.Type.URL);
            if (verify != null) {
                this.verifyMap.put(methodParameter, verify);
            }
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        try {
            Type parameterType = methodParameter.getGenericParameterType();
            this.validate(nativeWebRequest, methodParameter, type);

            Url url = methodParameter.getParameterAnnotation(Url.class);
            JavaType javaType = jacksonConverter.getJavaType(parameterType);
            String parameterName = url.value().equals("") ? methodParameter.getParameterName() : url.value();
            String formValue = this.getRequestParameterMap(nativeWebRequest, methodParameter, type).get(parameterName);
            return jacksonConverter.readValue(formValue, javaType);
        } catch (JsonProcessException ex) {
            throw new JsonProcessException("[Url : Data transformation failed. Please check whether the interface matches the input parameter]");
        } catch (ValidateException ex) {
            throw ex;
        } catch (CommentException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new UnsupportedException(ex);
        }
    }


}
